#定义一大堆变量，实质就是将需要多次重复用到的语句定义一个变量方便使用与替换
BUILD_DIR=myos/bin
ENTRY_POINT=0xc0001500
HD60M_PATH=/home/zengao/Desktop/operatorSystem/bochs/hd60M.img
#只需要把hd60m.img路径改成自己环境的路径，整个代码直接make all就完全写入了，能够运行成功
AS=nasm
CC=gcc-4.4
LD=ld
LIB= -I myos/lib/ -I myos/lib/kernel/ -I myos/kernel/ -I myos/device/ -I myos/thread/ -I myos/userprog/ -I myos/lib/user
ASFLAGS= -f elf
CFLAGS= -Wall $(LIB) -c -fno-builtin -W -Wstrict-prototypes -Wmissing-prototypes -m32 -fno-stack-protector
#-Wall warning all的意思，产生尽可能多警告信息，-fno-builtin不要采用内部函数，
#-W 会显示警告，但是只显示编译器认为会出现错误的警告
#-Wstrict-prototypes 要求函数声明必须有参数类型，否则发出警告。-Wmissing-prototypes 必须要有函数声明，否则发出警告

LDFLAGS= -Ttext $(ENTRY_POINT) -e main -Map $(BUILD_DIR)/kernel.map -m elf_i386
#-Map,生成map文件，就是通过编译器编译之后，生成的程序、数据及IO空间信息的一种映射文件
#里面包含函数大小，入口地址等一些重要信息

OBJS=$(BUILD_DIR)/main.o $(BUILD_DIR)/init.o \
	$(BUILD_DIR)/interrupt.o $(BUILD_DIR)/timer.o $(BUILD_DIR)/kernel.o \
	$(BUILD_DIR)/print.o ${BUILD_DIR}/debug.o ${BUILD_DIR}/string.o ${BUILD_DIR}/bitmap.o \
	${BUILD_DIR}/memory.o ${BUILD_DIR}/thread.o ${BUILD_DIR}/switch.o ${BUILD_DIR}/list.o \
	${BUILD_DIR}/console.o ${BUILD_DIR}/sync.o ${BUILD_DIR}/keyboard.o ${BUILD_DIR}/ioqueue.o \
	${BUILD_DIR}/process.o ${BUILD_DIR}/tss.o ${BUILD_DIR}/syscall.o ${BUILD_DIR}/syscall-init.o \
	${BUILD_DIR}/stdio.o
#顺序最好是调用在前，实现在后

######################编译两个启动文件的代码#####################################
boot:$(BUILD_DIR)/mbr.o $(BUILD_DIR)/loader.o
$(BUILD_DIR)/mbr.o:myos/boot/mbr.S
	@$(AS) -I myos/boot/include -o $@ $<
	
$(BUILD_DIR)/loader.o:myos/boot/loader.S
	@$(AS) -I myos/boot/include -o $@ $<
	
######################编译C内核代码###################################################
$(BUILD_DIR)/main.o:myos/kernel/main.c
	@$(CC) $(CFLAGS) -o $@ $<	
# $@表示规则中目标文件名的集合这里就是$(BUILD_DIR)/main.o  $<表示规则中依赖文件的第一个，这里就是kernle/main.c 

$(BUILD_DIR)/init.o:myos/kernel/init.c
	@$(CC) $(CFLAGS) -o $@ $<

$(BUILD_DIR)/interrupt.o:myos/kernel/interrupt.c
	@$(CC) $(CFLAGS) -o $@ $<

$(BUILD_DIR)/timer.o:myos/device/timer.c
	@$(CC) $(CFLAGS) -o $@ $<

$(BUILD_DIR)/console.o:myos/device/console.c
	@$(CC) $(CFLAGS) -o $@ $<

$(BUILD_DIR)/keyboard.o:myos/device/keyboard.c
	@$(CC) $(CFLAGS) -o $@ $<

$(BUILD_DIR)/ioqueue.o:myos/device/ioqueue.c
	@$(CC) $(CFLAGS) -o $@ $<

$(BUILD_DIR)/debug.o:myos/kernel/debug.c
	@$(CC) $(CFLAGS) -o $@ $<

$(BUILD_DIR)/string.o:myos/lib/kernel/string.c
	@$(CC) $(CFLAGS) -o $@ $<

$(BUILD_DIR)/bitmap.o:myos/lib/kernel/bitmap.c
	@$(CC) $(CFLAGS) -o $@ $<

$(BUILD_DIR)/list.o:myos/lib/kernel/list.c
	@$(CC) $(CFLAGS) -o $@ $<

$(BUILD_DIR)/syscall.o:myos/lib/user/syscall.c
	@$(CC) $(CFLAGS) -o $@ $<

$(BUILD_DIR)/memory.o:myos/kernel/memory.c
	@$(CC) $(CFLAGS) -o $@ $<

$(BUILD_DIR)/thread.o:myos/thread/thread.c
	@$(CC) $(CFLAGS) -o $@ $<

$(BUILD_DIR)/sync.o:myos/thread/sync.c
	@$(CC) $(CFLAGS) -o $@ $<

$(BUILD_DIR)/tss.o:myos/userprog/tss.c
	@$(CC) $(CFLAGS) -o $@ $<

$(BUILD_DIR)/process.o:myos/userprog/process.c
	@$(CC) $(CFLAGS) -o $@ $<

$(BUILD_DIR)/syscall-init.o:myos/userprog/syscall-init.c
	@$(CC) $(CFLAGS) -o $@ $<

$(BUILD_DIR)/stdio.o:myos/lib/stdio.c
	@$(CC) $(CFLAGS) -o $@ $<

###################编译汇编内核代码#####################################################
$(BUILD_DIR)/kernel.o:myos/kernel/kernel.S 
	@$(AS) $(ASFLAGS) -o $@ $<

$(BUILD_DIR)/print.o:myos/lib/kernel/print.S
	@$(AS) $(ASFLAGS) -o $@ $<

$(BUILD_DIR)/switch.o:myos/thread/switch.S
	@$(AS) $(ASFLAGS) -o $@ $<

##################链接所有内核目标文件##################################################
$(BUILD_DIR)/kernel.bin:$(OBJS)
	@$(LD) $(LDFLAGS) -o $@ $^
# $^表示规则中所有依赖文件的集合，如果有重复，会自动去重

.PHONY:mk_dir hd clean build all boot gdb_symbol	#定义了6个伪目标
mk_dir:
	@if [ ! -d $(BUILD_DIR) ];then mkdir $(BUILD_DIR);fi 
#判断build文件夹是否存在，如果不存在，则创建

hd:
	@dd if=${BUILD_DIR}/mbr.o of=$(HD60M_PATH) count=1 bs=512 conv=notrunc && \
	dd if=${BUILD_DIR}/loader.o of=$(HD60M_PATH) count=4 bs=512 seek=2 conv=notrunc && \
	dd if=$(BUILD_DIR)/kernel.bin of=$(HD60M_PATH) bs=512 count=200 seek=9 conv=notrunc
	
clean:
	@cd $(BUILD_DIR) && rm -f ./* && echo "remove myos/bin all done"
#-f, --force忽略不存在的文件，从不给出提示，执行make clean就会删除build下所有文件

build:$(BUILD_DIR)/kernel.bin
	
#执行build需要依赖kernel.bin，但是一开始没有，就会递归执行之前写好的语句编译kernel.bin

#生成可以被GDB理解的符号表，用于GDB调试
gdb_symbol:
	objcopy --only-keep-debug $(BUILD_DIR)/kernel.bin $(BUILD_DIR)/kernel.sym

all:mk_dir boot build hd gdb_symbol
#make all 就是依次执行mk_dir build hd